﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using ValidationFramework.Reflection;
using ValidationFramework.Extensions;

namespace ValidationFramework.Configuration.Fluent
{
	public class RuleLocationStep<TType> : IRuleLocationStep<TType>
	{
		private string _ruleSet;
		private TypePolicy _typePolicy;

		public RuleLocationStep(TypePolicy typePolicy)
		{
			_typePolicy = typePolicy;
			_ruleSet = string.Empty;
		}
		public RuleLocationStep(TypePolicy typePolicy, string ruleSet)
		{
			_typePolicy = typePolicy;
			_ruleSet = ruleSet;
		}
		
		// --- IRuleLocationOptions<TType> Members

		public RuleCreationStep<TType> EnsureParentOf<TReturnType>(Expression<Func<TType, TReturnType>> memberExpression)
		{
			var location = new RuleLocation(ResolvePolicy(memberExpression));
			location.RuleSet = _ruleSet;
			location.RuleScope = RuleScope.Parent;

			return new RuleCreationStep<TType>(location); // note the type to validate is TType - its the parent
		}

		public RuleCreationStep<TReturnType> Ensure<TReturnType>(Expression<Func<TType, TReturnType>> memberExpression)
		{
			var location = new RuleLocation(ResolvePolicy(memberExpression));
			location.RuleSet = _ruleSet;
			location.RuleScope = RuleScope.Member;

			return new RuleCreationStep<TReturnType>(location); // note the type to validate is TReturnType - its the member
		}

		private IValidationPolicy ResolvePolicy<TReturnType>(Expression<Func<TType, TReturnType>> memberExpression)
		{
			var name = (((MemberExpression)memberExpression.Body).Member).Name;
			var propKey = new PropertyKey(new TypeKey(typeof(TType).TypeHandle), name);
			return _typePolicy.GetOrCreatePropertyPolicy(propKey);
		}
	}
}
